import { RoutingContext } from 'dva';
import { matchPath, StaticRouter } from 'dva/router';
import { createMemoryHistory } from "history";
import { renderToString } from 'react-dom/server'
// import match from "react-router/lib/match"
import { join } from 'path';
import co from 'co';
import thunkify from 'thunkify-wrap';

import React from "react";
// import stateServe from './state_serve';
import Router, { routes } from '../../common/routes';
import createApp from '../../common/create-app';
import * as models from '../../common/models';
import ReactDOMServer from "react-dom/server";
import dva from 'dva';
// console.log('---开始require');



// console.log('------------开始了middle');
  module.exports = function (req, res, next) {
  const reducersMap = new Map();
  let currentNamespace = undefined;
  let initStates = {};
  const pathname = req.url;
  console.log('req.url', req.url);

  co(function* () {


    const matchRoutes = (routes, pathname, branches = []) => {
      routes
        .filter(route => !!route.path)
        .forEach(route => {
          // Check if the route is a match
          const match = matchPath(pathname, route);

          // If it is, check if it has child routes
          if (match) {
            if (route.routes) {
              // If it has child routes, recursion
              matchRoutes(route.routes, pathname, branches);
            }

            // Add the matched route to the branches
            branches.push({ route: route, match: match });
          }
        });

      return branches;
    };

    const matchedRoutes = matchRoutes(routes, pathname);
    console.log('----matchedRoutes', matchedRoutes)
    if (!matchedRoutes.length) {
      next();
      return null;
    }

    // Sort array so the most specific (exact) route is first
    matchedRoutes.sort((a, b) => {
      if (b.route.path === pathname) {
        return 1;
      }
      return -1;
    });

    // console.log('---服务端---');
    // 服务器渲染错误记录
    let serverGetDataError = undefined;
    // console.log(match);
    // console.log(routes, req.url)
    // console.log(match({
    //   routes: routes,
    //   location: req.url
    // }))
    // const matchedData = yield thunkify(match)({
    //   routes: routes,
    //   location: req.url
    // })
    //数组
    // const renderProps = matchedData[1];
    // if (!renderProps) {
    //   console.error(`Unexpected request! url: ${req.url}`);
    //   return {
    //     serverError: `Unexpected request! url: ${req.url}`,
    //   };
    // }


    // // 路由处理
    // if (route.namespace) {
    //   currentNamespace = route.namespace;
    // }
    console.log('---')

    // 处理models
    // if (models) {
    //   const _models = Object.keys(models).map(k => models[k]);
    //   for (const model of _models) {
    //     if (model.namespace === currentNamespace) {

    //       //创建传统reducers map;
    //       const namespace = model.namespace;
    //       if (typeof model.reducers === 'object') {
    //         const modelReducers = model.reducers;
    //         Object.keys(modelReducers)
    //           .map(k => reducersMap.set(`${namespace}__${k}`, modelReducers[k]))
    //       }

    //       // 获取初始化数据，服务器渲染
    //       // if (model.initData) {
    //       //   try {
    //       //     const allRes = yield Promise.all(
    //       //       Object.keys(model.initData)
    //       //         .map(k => model.initData[k])
    //       //         .map(fn => co(fn(
    //       //           { params: renderProps.params, location: renderProps.params },
    //       //           _mapEffect2State(model))
    //       //         ))
    //       //     );
    //       //   } catch (err) {
    //       //     console.error('###### server init data error. #####\n', err.stack);
    //       //     serverGetDataError = err.message;
    //       //   }
    //       // }
    //     }
    //   }
    // }
    const renderProps = matchedRoutes[0];
    const route = renderProps[renderProps.length - 1];
    // 准备HTML需要的信息
    const initialState = { ...initStates, _system: { serverGetDataError } };
    // 缓存states
    // const stateKey = yield stateServe.set(JSON.stringify(initialState));

    // const router = [], models = {};

    const app = dva({
      history: createMemoryHistory()
    });

    app.router(() => {
      return (
        <StaticRouter location={req.url} context={{}}>
          <Router history={createMemoryHistory()} />
        </StaticRouter>
      );
    });

    const html = ReactDOMServer.renderToString(app.start()());

    console.log('----什么鸡儿鬼');
    return {
      html
    }
    // const app = createApp({
    //   history: createMemoryHistory(),
    //   initialState,
    // }, { router: matchedRoutes, models }, /* isServer */true);
    // console.log('xxxx----', app);
    // const html = renderToString(app.start()());
    // return {
    //   html,
    //   stateKey,
    //   notFound: route.path === '*',
    // }
  }).then((data = {}) => {
    console.log('-----', data);
    if (data) {
      res.end(renderFullPage(data.html, data.stateKey));
    }
    // console.log('co res: ', data);
    // if (data.serverError) {
    //   res.end(data.serverError);
    // } else {
    // res.end(renderFullPage(data.html, data.stateKey));
    // }
  }).catch(err => {
    console.error(err);
  });

  //////////////////////////
  // helper functions
  function _mapEffect2State(model = {}) {
    function* put(action) {
      const reducer = reducersMap.get(`${model.namespace}__${action.type}`);
      const currentState = reducer(initStates, action);
      initStates = Object.assign(
        {},
        initStates,
        { [`${model.namespace}`]: Object.assign({}, initStates[`${model.namespace}`], currentState) }
      );
      yield initStates;
    }
    function call(fn, ...args) {
      return fn(args);
    }
    return { call, put };
  }
}

//  <script type="text/javascript" src="/states/${stateKey}.js"></script>
{/* <link rel="stylesheet" href="/public/index.css" /> */ }
{/* <script src="/public/vendor_dll.js"></script> */}
function renderFullPage(html, stateKey) {
  return `
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8" />
</head>
<body>
  <div id="root">
    <div>
      ${html}
    </div>
  </div>
  <script src="/public/vendor_dll.js"></script> 
  <script src="/public/index.js"></script>
</body>
</html>
  `;
}